# -*- coding:utf-8 -*-
"""
@Author : 审心
@Time : 2023/3/23 17:06
此包用于完成获取竞争对手关键词数据
"""

import time
import traceback

import pandas as pd

from common import glv
from dataclasses import dataclass, field
from typing import List, Optional, Union
from DrissionPage import WebPage
from autoTask.taobao.sycm.gjc.competitorGoodKey.publicResource import GoodsFeature, __links as links, \
    wait_tb_complete, CategorySearch
from autoTask.taobao.sycm.utils.close_Ad import close_ad
from common.logger.log import log_
from common.utils.ThreadUtil import before_enable_stop_abel_thread
from common.utils.web_page_util import MockTap, Tap
from common.utils.urlUtil import url_get_params
from common.utils.listUtil import list_has_element
from autoTask.taobao.sycm.gjc.competitorGoodKey.findCompetingProductsAction.find_competing_products import \
    FindCompetingProducts
from autoTask.taobao.sycm.gjc.competitorGoodKey.getCompetingKeyAction.get_competing_key import GetCompetingKey


@dataclass
class CompetitorGoodKey:
    """
    用于完成获取竞争对手关键词数据
    :param page: 网页对象
    :param category_search_list: 分类搜索对象列表
    :param ignore_keys: 需要忽略的关键词
    :param key_is_not_contain_letter: 关键词中是否不包含字母
    :param competing_min_visits 竞争关键词最低访问数
    :param competing_min_roi 竞争关键词最低 roi (百分比 : 10.20)
    :param is_test_execute 是否测试执行
    """
    page: Optional[WebPage]
    category_search_list: List[CategorySearch]
    ignore_keys: List[str] = field(default_factory=list)
    key_is_not_contain_letter: bool = False
    competing_min_visits: int = 0
    competing_min_roi: float = 0
    is_test_execute: bool = False

    @before_enable_stop_abel_thread(target_func=close_ad, is_loop=True)
    def __call__(self) -> Union[tuple[None, None], tuple[Optional[str], str]]:
        """
        调用此方法即可启动本任务
        :return: (任务附件路径, 附件后缀名称)
        """
        # 跳转到任务首页
        self.to_init_page()
        try:
            target_goods = {}
            for category_search in self.category_search_list:
                try:
                    # 指定商品不获取目标商品
                    if len(category_search.goods_feature_list) == 0:
                        # 设置标准类目
                        self.set_base_category(category_search.name)
                        # 获取目标商品
                        category_search.goods_feature_list = self.get_my_goods_features(category_search)
                    # 设置目标商品的竞品
                    goods_features = FindCompetingProducts(self.page,
                                                           category=category_search.name,
                                                           date_cycle=category_search.date_cycle,
                                                           goods_features=category_search.goods_feature_list,
                                                           ignore_name_list=category_search.ignore_name_list,
                                                           contain_name_list=category_search.contain_name_list)()
                    if len(goods_features) > 0:
                        if target_goods.get(category_search.name):
                            target_goods[category_search.name] += goods_features
                        else:
                            target_goods[category_search.name] = goods_features
                except:
                    log_.error(f"获取品类 : {category_search.name} 竞品时失败")
                    log_.error(traceback.format_exc())
            log_.info(f"目标商品 : \n {target_goods}")
            if len(target_goods) == 0:
                log_.warning(f"GetCompetingKey -> 没有目标商品 : {self}")
                return None, None
            # 获取竞品关键词数据
            path = GetCompetingKey(self.page, target_goods, self.ignore_keys,
                                   competing_min_roi=self.competing_min_roi,
                                   competing_min_visits=self.competing_min_visits,
                                   is_test_execute=self.is_test_execute,
                                   is_return_excel_path=True,
                                   key_is_not_contain_letter=self.key_is_not_contain_letter)()
        finally:
            glv.set_item("关键词搜索分析缓存", pd.DataFrame())
        return path, ".zip"

    def to_init_page(self):
        """
        跳转到任务初始界面
        :return:
        """
        if not self.page.url.startswith(links["生意参谋首页"]) and not self.page.url.startswith(links["品类_商品排行"]):
            self.page.get(links["生意参谋首页"], retry=5, interval=3, timeout=10)
        if not self.page.url.startswith(links["品类_商品排行"]):
            MockTap("x://span[.='品类']", before_delay=(2, 4))(self.page)
            # 监听表格数据刷新
            self.page.wait.load_complete(30)

    def set_base_category(self, category: str):
        """
        设置标准类目
        :param category 品类名称
        :return:
        """
        # 跳转到任务首页
        self.to_init_page()
        # 点击跳转到商品排行刷新设置
        MockTap(self.page("tag=span@@text()=商品排行"), "点击商品排行标签页跳转失败", after_delay=3)()
        MockTap(self.page("tag=span@@text()=30天"), "设置数据周期为30天", after_delay=3)()
        # 点击设置类目打开下拉框
        MockTap(self.page("t:span@class=short-name"), "打开设置类目下拉窗失败", after_delay=3, reduce_scope=(10, 5))()
        # 输入关键词搜索
        self.page("@@class=ant-input@@placeholder:请输入关键字").input(category)
        time.sleep(3)
        # 点击对应关键词
        Tap(self.page(f"@@class^oui-typeahead-dropdown-item@@text():{category}"), "点击搜索结果中的关键词失败")()
        # 等待表格刷新
        wait_tb_complete(self.page)

    def get_my_goods_features(self, category_search: CategorySearch):
        """
        获取我的商品的特征
        :param category_search: 品类搜索对象
        :return: 商品特征列表
        :rtype: list[GoodsFeatures]
        """
        if len(category_search.goods_feature_list) == 0:
            # 检查当前标准品类设置是否正确
            if not self.page(f"@@class=short-name@@text():{category_search.name}", timeout=0):
                self.set_base_category(category_search.name)
            # 获取表格元素中的商品标题元素列表
            title_list = [ele for ele in self.page(".ant-table-body").eles(".singleGoodsName", timeout=0)
                          if all(c in ele.text for c in category_search.contain_name_list)]
            for ele in title_list:
                MockTap(ele, after_delay=3, scope_random=False)()
                # 等待新标签页出现
                self.page.wait.new_tab()
                # 获取新标签页对象
                new_tab = self.page.get_tab(self.page.latest_tab)
                # 等待新标签页加载
                new_tab.wait.load_start()
                goods_features = GoodsFeature().set_by_page(new_tab, url_get_params(new_tab.url, 'id'))
                if goods_features is not None and goods_features.__getattribute__("min_price") is not None \
                        and not list_has_element(category_search.goods_feature_list, goods_features):
                    category_search.goods_feature_list.append(goods_features)
                self.page.close_tabs(tabs_or_ids=(new_tab.tab_id,))
            self.page.close_other_tabs()
        return category_search.goods_feature_list
